#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>
#include <semaphore.h>
#include "hfile.h"


#define MAXPENDING 5    //Max aantal conecties
#define BUFFSIZE 32
#define CMDSIZE 50
#define ARGSIZE BUFLEN - CMDSIZE

void Die(char *mess)    //Methode voor weergeven fouten
{
    perror(mess); exit(1);
}

int recv_data(int descClient, char *message, int len, int flags);
int sendToFsp(char *Buffer);
int recvFromFsp(char *buffer);


//Shared buffer for mmap
char *dataBuffer;//Buffer for sending data

//create semaphore
sem_t *semUpFull;
sem_t *semUpEmpty;
sem_t *semDownFull;
sem_t *semDownEmpty;
sem_t *semComChanPost;
sem_t *semComChanRead;

int main()
{
      if(sem_unlink("semUpFull") <0)
      {
        perror("unlinksemUpFull");
      }

       if(sem_unlink("semDownEmpty") <0)
      {
        perror("unlinksemdownempty");
      }

       if(sem_unlink("semComChanPost") <0)
      {
        perror("unlinksemComChanPost");
      }

      
    if((semUpFull = sem_open("semUpFull", O_CREAT, 0664, 0)) == SEM_FAILED)
    {
        perror("Open semUpFull");
        if(sem_unlink("semUpFull") <0)
        {
            perror("Unlink at error semUpFull");
        }
    }

    if((semComChanPost = sem_open("semComChanPost", O_CREAT, 0644, 0)) == SEM_FAILED)
    {
        perror("Open semComChanPost");
        if(sem_unlink("semComChanPost") <0)
        {
            perror("Unlink at error semComChanPost");
        }
    }

    if((semDownEmpty = sem_open("semDownEmpty", O_CREAT, 0644, 0)) == SEM_FAILED)
    {
        perror("Open semDownEmpty");
        if(sem_unlink("semDownEmpty") <0)
        {
            perror("Unlink at error semDownEmpty");
        }
    }
      
    //Client handler variables
    int serversock, clientsock;
    struct sockaddr_in echoserver, echoclient;
 
    //Maak TCP socket aan voor echo server
    if ((serversock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
    {
        Die("Failed to create socket");
    }

    //Vul socket met family, incomend ip en port
    memset(&echoserver, 0, sizeof(echoserver));       //Maak geheugen ruimte schoon
    echoserver.sin_family = AF_INET;                  //Family
    echoserver.sin_addr.s_addr = htonl(INADDR_ANY);   //Incomend addr stot deze in s_addr dmv Host to Long
    echoserver.sin_port = htons(5002);                //Port

    //re use addr
     int yes = 1;

     if (setsockopt(serversock, SOL_SOCKET, SO_REUSEADDR, &yes,sizeof(int)) == -1)
     {
          perror("setsockopt");
          exit(EXIT_FAILURE);
     }

   //Bind server socket
   if (bind(serversock, (struct sockaddr *) &echoserver,sizeof(echoserver)) < 0)
   {
        Die("Failed to bind the server socket");
   }

   //Zet listen mode aan op socket dus luster op socket
   if (listen(serversock, MAXPENDING) < 0)
   {
        Die("Failed to listen on server socket");
   }

       printf("Maak memmap upload\n");

       //Make memmap
       memmap();
       printf("Maak memmap comchan\n");
       memmapcomchan();

       printf("File server draait\n");

   //Loop voor server
   while (1)
   {
        unsigned int clientlen = sizeof(echoclient);

        if ((clientsock = accept(serversock, (struct sockaddr *) &echoclient,&clientlen)) < 0)
        {
            Die("Failed to accept client connection");
        }
 
        printf("Client conected with number: %d\n", clientsock);


        char buffer[BUFLEN];
        int received = -1;

        while(1)    //Loop for command
        {
            //Wait until message is recived
            if ((received = recv(clientsock, buffer, BUFLEN, 0)) < 0)
            {
                 Die("Ontvangen van data mislukt");
            }
            //buffer for commandline, dataBuffer for sending and recving functions
            commandAna(clientsock, buffer, dataBuffer);
        }   
   }
}